package it.polimi.traveldream.ejb.entities;

import it.polimi.traveldream.ejbclient.dtos.TravelPackageDTO;
import it.polimi.traveldream.utils.enums.PackageType;

import java.io.Serializable;

import javax.persistence.*;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;


/**
 * The persistent class for the travelpackage database table.
 * 
 */
@Entity
@NamedQueries({
	@NamedQuery(name=Travelpackage.FIND_PACKAGES_AVAILABLE,
			query="SELECT t FROM Travelpackage t WHERE t.feasibleReservations > 0 AND t.overpast = false"),
	@NamedQuery(name=Travelpackage.FIND_PACKAGES,
			query="SELECT t FROM Travelpackage t WHERE t.overpast = :overpast"),
	@NamedQuery(name=Travelpackage.FIND_PACKAGES_NOTEXPIRED,
			query="SELECT t FROM Travelpackage t WHERE t.expiry > current_timestamp"),
	@NamedQuery(name=Travelpackage.FIND_PACKAGES_BY_HOTEL_PLACE,
		query="SELECT t FROM Travelpackage t, Hotelcomposition hc, Hotel h WHERE t.id = hc.id.travelPackage AND hc.id.hotel = h.id AND upper(h.address) LIKE upper(:place) AND t.overpast = false"),
	@NamedQuery(name=Travelpackage.FIND_PACKAGES_BY_TRANSPORT_PLACE,
		query="SELECT t FROM Travelpackage t, Transportcomposition tc, Transport tr WHERE t.id = tc.id.travelPackage AND tc.id.transport = tr.id AND (upper(tr.departureCity) LIKE upper(:place) OR upper(tr.arrivalCity) LIKE upper(:place)) AND t.overpast = false"),
	@NamedQuery(name=Travelpackage.FIND_PACKAGES_BY_EXCURSION_PLACE,
		query="SELECT t FROM Travelpackage t, Excursioncomposition ec, Excursion e WHERE t.id = ec.id.travelPackage AND ec.id.excursion = e.id AND upper(e.startAddress) LIKE upper(:place) AND t.overpast = false")
})
public class Travelpackage implements Serializable {
	private static final long serialVersionUID = -5052809753716968888L;
	public static final String FIND_PACKAGES_AVAILABLE = "Travelpackage.findPackagesAvailable";
	public static final String FIND_PACKAGES = "Travelpackage.findPackages";
	public static final String FIND_PACKAGES_NOTEXPIRED = "Travelpackage.findPackagesNotExpired";
	public static final String FIND_PACKAGES_BY_HOTEL_PLACE = "Travelpackage.findPackagesByHotelPlace";
	public static final String FIND_PACKAGES_BY_TRANSPORT_PLACE = "Travelpackage.findPackagesByTransportPlace";
	public static final String FIND_PACKAGES_BY_EXCURSION_PLACE = "Travelpackage.findPackagesByExcursionPlace";
	private int id;
	private BigDecimal basePrice;
	private String description;
	private Date endTrip;
	private Date expiry;
	private int feasibleReservations;
	private boolean overpast;
	private Date startTrip;
	private PackageType type;
	private Composedpredefinedpackage composedpredefinedpackage;
	private List<Excursion> excursions;
	private List<Hotel> hotels;
	private List<Participation> participations;
	private List<Transport> transports;

	public Travelpackage() {
		super();
	}
	
	public Travelpackage(TravelPackageDTO travelPackage) {
		super();
		this.id = travelPackage.getId();
		this.basePrice = travelPackage.getBasePrice();
		this.description = travelPackage.getDescription();
		this.endTrip = travelPackage.getEndTrip();
		this.expiry = travelPackage.getExpiry();
		this.feasibleReservations = travelPackage.getFeasibleReservations();
		this.overpast = travelPackage.isOverpast();
		this.startTrip = travelPackage.getStartTrip();
		this.type = travelPackage.getType();
		handleAdderEmployee(travelPackage);
	}

	private void handleAdderEmployee(TravelPackageDTO travelPackage) {
		if(travelPackage.getAdderEmployee() != null) {
			this.composedpredefinedpackage = new Composedpredefinedpackage(
					travelPackage.getTimestampComposition(), this,
					new User(travelPackage.getAdderEmployee()));
		}
	}

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	public int getId() {
		return this.id;
	}

	public void setId(int id) {
		this.id = id;
	}


	public BigDecimal getBasePrice() {
		return this.basePrice;
	}

	public void setBasePrice(BigDecimal basePrice) {
		this.basePrice = basePrice;
	}


	public String getDescription() {
		return this.description;
	}

	public void setDescription(String description) {
		this.description = description;
	}


	@Temporal(TemporalType.TIMESTAMP)
	public Date getEndTrip() {
		return this.endTrip;
	}

	public void setEndTrip(Date endTrip) {
		this.endTrip = endTrip;
	}


	@Temporal(TemporalType.TIMESTAMP)
	public Date getExpiry() {
		return this.expiry;
	}

	public void setExpiry(Date expiry) {
		this.expiry = expiry;
	}


	public int getFeasibleReservations() {
		return this.feasibleReservations;
	}

	public void setFeasibleReservations(int feasibleReservations) {
		this.feasibleReservations = feasibleReservations;
	}


	public boolean getOverpast() {
		return this.overpast;
	}

	public void setOverpast(boolean overpast) {
		this.overpast = overpast;
	}


	@Temporal(TemporalType.TIMESTAMP)
	public Date getStartTrip() {
		return this.startTrip;
	}

	public void setStartTrip(Date startTrip) {
		this.startTrip = startTrip;
	}

	@Enumerated(EnumType.STRING)
	public PackageType getType() {
		return this.type;
	}

	public void setType(PackageType type) {
		this.type = type;
	}


	//bi-directional one-to-one association to Composedpredefinedpackage
	@OneToOne(mappedBy="travelpackage", cascade = CascadeType.PERSIST)
	public Composedpredefinedpackage getComposedpredefinedpackage() {
		return this.composedpredefinedpackage;
	}

	public void setComposedpredefinedpackage(Composedpredefinedpackage composedpredefinedpackage) {
		this.composedpredefinedpackage = composedpredefinedpackage;
	}


	//bi-directional many-to-many association to Excursion
	@ManyToMany
	@JoinTable(
		name="excursioncomposition"
		, joinColumns={
			@JoinColumn(name="TravelPackage")
			}
		, inverseJoinColumns={
			@JoinColumn(name="Excursion")
			}
		)
	public List<Excursion> getExcursions() {
		return this.excursions;
	}

	public void setExcursions(List<Excursion> excursions) {
		this.excursions = excursions;
	}


	//bi-directional many-to-many association to Hotel
	@ManyToMany
	@JoinTable(
		name="hotelcomposition"
		, joinColumns={
			@JoinColumn(name="TravelPackage")
			}
		, inverseJoinColumns={
			@JoinColumn(name="Hotel")
			}
		)
	public List<Hotel> getHotels() {
		return this.hotels;
	}

	public void setHotels(List<Hotel> hotels) {
		this.hotels = hotels;
	}

	//bi-directional many-to-one association to Participation
	@OneToMany(mappedBy="travelpackage")
	public List<Participation> getParticipations() {
		return this.participations;
	}

	public void setParticipations(List<Participation> participations) {
		this.participations = participations;
	}

	public Participation addParticipation(Participation participation) {
		getParticipations().add(participation);
		participation.setTravelpackage(this);

		return participation;
	}

	public Participation removeParticipation(Participation participation) {
		getParticipations().remove(participation);
		participation.setTravelpackage(null);

		return participation;
	}


	//bi-directional many-to-many association to Transport
	@ManyToMany
	@JoinTable(
		name="transportcomposition"
		, joinColumns={
			@JoinColumn(name="TravelPackage")
			}
		, inverseJoinColumns={
			@JoinColumn(name="Transport")
			}
		)
	public List<Transport> getTransports() {
		return this.transports;
	}

	public void setTransports(List<Transport> transports) {
		this.transports = transports;
	}

}